This is an automated email from the ASF dual-hosted git repository.

davin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil-vscode.git


The following commit(s) were added to refs/heads/main by this push:
     new b807720  Implemented Relative Seek Offset Traversal
b807720 is described below

commit b807720b89abf737afeb67e4f366ba5184761cb9
Author: Robert Strickland <[email protected]>
AuthorDate: Thu Aug 31 09:06:45 2023 -1000

    Implemented Relative Seek Offset Traversal
    
    - Added Relative and Absolute seek offset determination and traversal.
    
    Closes #799
---
 .../DataDisplays/Header/DisplayHeader.svelte       | 19 +++++-
 src/svelte/src/components/Error/Error.svelte       |  7 ++-
 .../Header/fieldsets/SearchReplace.svelte          | 17 +++++-
 .../components/Header/fieldsets/SearchReplace.ts   |  7 +++
 src/svelte/src/components/dataEditor.svelte        |  4 --
 src/svelte/src/stores/index.ts                     | 67 +++++++++++++++++++---
 6 files changed, 102 insertions(+), 19 deletions(-)

diff --git a/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte 
b/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte
index 055cb2d..ce26a4b 100644
--- a/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte
+++ b/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte
@@ -22,6 +22,7 @@ limitations under the License.
     seekOffset,
     seekOffsetInput,
     selectionDataStore,
+    seekOffsetSearchType,
     selectionSize,
     bytesPerRow,
     viewport,
@@ -35,6 +36,7 @@ limitations under the License.
   } from '../../../stores/configuration'
   import { UIThemeCSSClass } from '../../../utilities/colorScheme'
   import { createEventDispatcher } from 'svelte'
+  import { OffsetSearchType } from '../../Header/fieldsets/SearchReplace'
 
   type ViewportDivSpread = '24px' | '28px' | '68px'
 
@@ -103,9 +105,20 @@ limitations under the License.
 
   function updateAddressValue(event: Event) {
     const addrSelect = event.target as HTMLSelectElement
-    const newSeekInput = $seekOffset.toString(parseInt(addrSelect.value))
-    $seekOffsetInput = newSeekInput === 'NaN' ? '0' : newSeekInput
-    $addressRadix = parseInt(addrSelect.value) as RadixValues
+    const newAddrRadix = parseInt(addrSelect.value) as RadixValues
+
+    if ($seekOffsetSearchType === OffsetSearchType.RELATIVE) {
+      const sign = $seekOffsetInput.substring(0, 1)
+      const value = parseInt(
+        $seekOffsetInput.substring(1),
+        $addressRadix
+      ).toString(newAddrRadix)
+      $seekOffsetInput = value === 'NaN' ? '0' : sign + value
+    } else {
+      const newSeekInput = $seekOffset.toString(parseInt(addrSelect.value))
+      $seekOffsetInput = newSeekInput === 'NaN' ? '0' : newSeekInput
+    }
+    $addressRadix = newAddrRadix
   }
 
   function clearDataDisplays() {
diff --git a/src/svelte/src/components/Error/Error.svelte 
b/src/svelte/src/components/Error/Error.svelte
index 7e672b7..86e170c 100644
--- a/src/svelte/src/components/Error/Error.svelte
+++ b/src/svelte/src/components/Error/Error.svelte
@@ -15,15 +15,18 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 -->
 <script lang="ts">
+  import Tooltip from '../layouts/Tooltip.svelte'
   import type { ErrorStore } from './Error'
 
   export let err: ErrorStore
   export let display: boolean
 </script>
 
-<div class="display" title={$err}>
+<div class="display">
   {#if display}
-    {@html err.innerHTML()}
+    <Tooltip alwaysEnabled={true} description={$err}>
+      {@html err.innerHTML()}
+    </Tooltip>
   {/if}
 </div>
 
diff --git a/src/svelte/src/components/Header/fieldsets/SearchReplace.svelte 
b/src/svelte/src/components/Header/fieldsets/SearchReplace.svelte
index 0ba4114..12c8c90 100644
--- a/src/svelte/src/components/Header/fieldsets/SearchReplace.svelte
+++ b/src/svelte/src/components/Header/fieldsets/SearchReplace.svelte
@@ -29,7 +29,8 @@ limitations under the License.
     searchErr,
     searchQuery,
     seekErr,
-    dataFeedAwaitRefresh,
+    seekOffsetSearchType,
+    seekOffset,
   } from '../../../stores'
   import { vscode } from '../../../utilities/vscode'
   import { MessageCommand } from '../../../utilities/message'
@@ -47,6 +48,8 @@ limitations under the License.
   } from '../../../utilities/highlights'
   import { viewport } from '../../../stores'
   import { EditActionRestrictions } from '../../../stores/configuration'
+  import { OffsetSearchType } from './SearchReplace'
+  import Tooltip from '../../layouts/Tooltip.svelte'
 
   const eventDispatcher = createEventDispatcher()
 
@@ -281,7 +284,17 @@ limitations under the License.
         allowDefaultInput="true"
         bind:value={$seekOffsetInput}
         on:inputEnter={handleInputEnter}
-      />
+      >
+        {#if $seekOffsetSearchType === OffsetSearchType.RELATIVE}
+          <Tooltip
+            alwaysEnabled={true}
+            description={'Offset input is relative to current offset: ' +
+              $seekOffset.toString($addressRadix)}
+          >
+            <span class="btn-icon material-symbols-outlined">my_location</span>
+          </Tooltip>
+        {/if}
+      </Input>
       <Error
         err={seekErr}
         display={$seekOffsetInput.length > 0 && !$seekable.valid}
diff --git a/src/svelte/src/components/Header/fieldsets/SearchReplace.ts 
b/src/svelte/src/components/Header/fieldsets/SearchReplace.ts
index 089ec07..e1f739b 100644
--- a/src/svelte/src/components/Header/fieldsets/SearchReplace.ts
+++ b/src/svelte/src/components/Header/fieldsets/SearchReplace.ts
@@ -19,6 +19,13 @@ import { SimpleWritable } from '../../../stores/localStore'
 import { addressRadix, seekOffsetInput } from '../../../stores'
 import { get } from 'svelte/store'
 
+export enum OffsetSearchType {
+  ABSOLUTE,
+  RELATIVE,
+}
+
+export type RelativeSeekSign = '+' | '-'
+
 interface QueryableData {
   input: string
   processing: boolean
diff --git a/src/svelte/src/components/dataEditor.svelte 
b/src/svelte/src/components/dataEditor.svelte
index 5ed6520..c4984bf 100644
--- a/src/svelte/src/components/dataEditor.svelte
+++ b/src/svelte/src/components/dataEditor.svelte
@@ -112,10 +112,6 @@ limitations under the License.
     return boundaryTripped
   }
 
-  function target_offset_in_viewport(offset: number): boolean {
-    return offset >= $viewport.fileOffset && offset <= $viewport.length
-  }
-
   function seek(offsetArg?: number) {
     if (!offsetArg) offsetArg = $seekOffset
 
diff --git a/src/svelte/src/stores/index.ts b/src/svelte/src/stores/index.ts
index 185cba1..5c7eaee 100644
--- a/src/svelte/src/stores/index.ts
+++ b/src/svelte/src/stores/index.ts
@@ -22,6 +22,7 @@ import { derived, writable } from 'svelte/store'
 import { SimpleWritable } from './localStore'
 import { ErrorComponentType, ErrorStore } from '../components/Error/Error'
 import {
+  line_num_to_file_offset,
   radixBytePad,
   regexEditDataTest,
   validateEncodingStr,
@@ -32,6 +33,7 @@ import {
   type ByteValue,
 } from '../components/DataDisplays/CustomByteDisplay/BinaryData'
 import {
+  OffsetSearchType,
   ReplaceQuery,
   SearchQuery,
 } from '../components/Header/fieldsets/SearchReplace'
@@ -150,6 +152,18 @@ export const regularSizedFile = derived(fileMetrics, 
($fileMetrics) => {
   return $fileMetrics.computedSize >= 2
 })
 
+export const dataFeedLineTopOffset = derived(
+  [dataFeedLineTop, viewport, bytesPerRow],
+  ([$dataFeedLineTop, $viewport, $bytesPerRow]) => {
+    const offset = line_num_to_file_offset(
+      $dataFeedLineTop,
+      $viewport.fileOffset,
+      $bytesPerRow
+    )
+    return Math.min(Math.max(0, offset), viewport.offsetMax)
+  }
+)
+
 export const searchable = derived(
   [searchQuery, editorEncoding],
   ([$searchQuery, $editorEncoding]) => {
@@ -218,14 +232,38 @@ export const selectionSize = derived(
   }
 )
 
+// How to handle the offset given in the input field for seek
+export const seekOffsetSearchType = derived(
+  seekOffsetInput,
+  ($seekOffsetInput) => {
+    const sign = $seekOffsetInput.substring(0, 1)
+    return sign === '+' || sign === '-'
+      ? OffsetSearchType.RELATIVE
+      : OffsetSearchType.ABSOLUTE
+  },
+  OffsetSearchType.ABSOLUTE
+)
+
 // derived from the seek offset input and the current address radix
 export const seekOffset = derived(
-  [seekOffsetInput, addressRadix],
-  ([$seekOffsetInput, $addressRadix]) => {
-    return $seekOffsetInput.length > 0
-      ? Math.max(0, parseInt($seekOffsetInput, $addressRadix))
-      : 0
-  }
+  [seekOffsetInput, seekOffsetSearchType, dataFeedLineTopOffset, addressRadix],
+  ([
+    $seekOffsetInput,
+    $seekOffsetSearchType,
+    $dataFeedLineTopOffset,
+    $addressRadix,
+  ]) => {
+    if ($seekOffsetSearchType === OffsetSearchType.ABSOLUTE) {
+      return $seekOffsetInput.length > 0
+        ? Math.max(0, parseInt($seekOffsetInput, $addressRadix))
+        : 0
+    } else
+      return (
+        Math.max(0, $dataFeedLineTopOffset) +
+        parseInt($seekOffsetInput, $addressRadix)
+      )
+  },
+  0
 )
 
 // derived readable string whose value is the selected encoded byte value with 
respect to the current focused viewport
@@ -371,11 +409,24 @@ export const applicable = derived(
 
 // derived readable boolean that indicates if the seek offset input is valid
 export const seekable = derived(
-  [seekOffset, seekOffsetInput, viewport, addressRadix],
-  ([$seekOffset, $seekOffsetInput, $viewport, $addressRadix]) => {
+  [seekOffset, seekOffsetInput, seekOffsetSearchType, viewport, addressRadix],
+  ([
+    $seekOffset,
+    $seekOffsetInput,
+    $seekOffsetSearchType,
+    $viewport,
+    $addressRadix,
+  ]) => {
+    $seekOffsetInput =
+      $seekOffsetSearchType === OffsetSearchType.RELATIVE
+        ? $seekOffsetInput.substring(1)
+        : $seekOffsetInput
+
     if ($seekOffsetInput.length <= 0) return { valid: false, seekErrMsg: '' }
     if ($seekOffset > viewport.offsetMax)
       return { valid: false, seekErrMsg: 'Exceeds filesize' }
+    if ($seekOffset < 0)
+      return { valid: false, seekErrMsg: 'Target offset < 0' }
     if (!regexEditDataTest($seekOffsetInput, $addressRadix))
       return { valid: false, seekErrMsg: 'Invalid characters' }
     return { valid: true, seekErrMsg: '' }

Reply via email to